\end{quote}
-Finally, as an optimization it is possible for each guest OS
-to install one ``fast trap'': this is a trap gate which will
-allow direct transfer of control from ring 3 into ring 1 without
-indirecting via Xen. In most cases this is suitable for use by
-the guest OS system call mechanism, although it may be used for
-any purpose.
-
-
-\begin{quote}
-\hypercall{set\_fast\_trap(int idx)}
-
-Install the handler for exception vector {\tt idx} as the ``fast
-trap'' for this domain. Note that this installs the current handler
-(i.e. that which has been installed more recently via a call
-to {\tt set\_trap\_table()}).
-
-\end{quote}
-
\section{Scheduling and Timer}
return ret;
}
-static __inline__ int HYPERVISOR_set_fast_trap(int idx)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_fast_trap),
- _a1 (idx) : "memory" );
-
- return ret;
-}
-
static __inline__ int HYPERVISOR_dom_mem_op(void *dom_mem_op)
{
int ret;
if ((error = HYPERVISOR_set_trap_table(trap_table)) != 0) {
panic("set_trap_table failed - error %d\n", error);
}
- if ((error = HYPERVISOR_set_fast_trap(0x80)) != 0) {
- panic("set_fast_trap failed - error %d\n", error);
- }
HYPERVISOR_set_callbacks(GSEL(GCODE_SEL, SEL_KPL), (unsigned long)Xhypervisor_callback,
GSEL(GCODE_SEL, SEL_KPL), (unsigned long)failsafe_callback);
}
#endif
-static int
+static void
cpu_mp_trap_init(trap_info_t *trap_ctxt)
{
-
trap_info_t *t = trap_table;
for (t = trap_table; t->address; t++) {
trap_ctxt[t->vector].cs = t->cs;
trap_ctxt[t->vector].address = t->address;
}
- return 0x80 /*SYSCALL_VECTOR*/;
}
/*
ctxt.trap_ctxt[i].vector = i;
ctxt.trap_ctxt[i].cs = FLAT_KERNEL_CS;
}
- ctxt.fast_trap_idx = cpu_mp_trap_init(ctxt.trap_ctxt);
+ cpu_mp_trap_init(ctxt.trap_ctxt);
/* No LDT. */
ctxt.ldt_ents = 0;
return ret;
}
-static inline int
-HYPERVISOR_set_fast_trap(int idx)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_set_fast_trap),
- "b" (idx) : "memory" );
-
- return ret;
-}
-
static inline int
HYPERVISOR_dom_mem_op(unsigned int op,
unsigned long *pages,
void __init trap_init(void)
{
HYPERVISOR_set_trap_table(trap_table);
- HYPERVISOR_set_fast_trap(SYSCALL_VECTOR);
/*
* The default LDT is a single-entry callgate to lcall7 for iBCS and a
extern void startup_32_smp(void);
extern void hypervisor_callback(void);
extern void failsafe_callback(void);
- extern int smp_trap_init(trap_info_t *);
+ extern void smp_trap_init(trap_info_t *);
int i;
cpu = ++cpucount;
ctxt.trap_ctxt[i].vector = i;
ctxt.trap_ctxt[i].cs = FLAT_KERNEL_CS;
}
- ctxt.fast_trap_idx = smp_trap_init(ctxt.trap_ctxt);
+ smp_trap_init(ctxt.trap_ctxt);
/* No LDT. */
ctxt.ldt_ents = 0;
void __init trap_init(void)
{
HYPERVISOR_set_trap_table(trap_table);
- HYPERVISOR_set_fast_trap(SYSCALL_VECTOR);
/*
* default LDT is a single-entry callgate to lcall7 for iBCS
cpu_init();
}
-int smp_trap_init(trap_info_t *trap_ctxt)
+void smp_trap_init(trap_info_t *trap_ctxt)
{
trap_info_t *t = trap_table;
trap_ctxt[t->vector].cs = t->cs;
trap_ctxt[t->vector].address = t->address;
}
- return SYSCALL_VECTOR;
}
return ret;
}
-static inline int
-HYPERVISOR_set_fast_trap(
- int idx)
-{
- int ret;
- unsigned long ign;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign)
- : "0" (__HYPERVISOR_set_fast_trap), "1" (idx)
- : "memory" );
-
- return ret;
-}
-
static inline int
HYPERVISOR_dom_mem_op(
unsigned int op, unsigned long *extent_list,
return ret;
}
-static inline int
-HYPERVISOR_set_fast_trap(
- int idx)
-{
- int ret;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret)
- : "0" ((unsigned long)__HYPERVISOR_set_fast_trap), "D" ((unsigned long)idx)
- : __syscall_clobber );
-
- return ret;
-}
-
static inline int
HYPERVISOR_dom_mem_op(
unsigned int op, unsigned long *extent_list,
return ret;
}
-static inline int
-HYPERVISOR_set_fast_trap(int idx)
-{
- int ret;
- unsigned long ign1;
-
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret), "=b" (ign1)
- : "0" (__HYPERVISOR_set_fast_trap), "1" (idx)
- : "memory" );
-
- return ret;
-}
-
static inline int
HYPERVISOR_dom_mem_op(unsigned int op, unsigned long *extent_list,
unsigned long nr_extents, unsigned int extent_order)
ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
}
-#if defined(__i386__)
- ctxt->fast_trap_idx = 0;
-#endif
-
/* No LDT. */
ctxt->ldt_ents = 0;
* 1. user_regs is fine, as Xen checks that on context switch.
* 2. fpu_ctxt is fine, as it can't hurt Xen.
* 3. trap_ctxt needs the code selectors checked.
- * 4. fast_trap_idx is checked by Xen.
- * 5. ldt base must be page-aligned, no more than 8192 ents, ...
- * 6. gdt already done, and further checking is done by Xen.
- * 7. check that kernel_ss is safe.
- * 8. pt_base is already done.
- * 9. debugregs are checked by Xen.
- * 10. callback code selectors need checking.
+ * 4. ldt base must be page-aligned, no more than 8192 ents, ...
+ * 5. gdt already done, and further checking is done by Xen.
+ * 6. check that kernel_ss is safe.
+ * 7. pt_base is already done.
+ * 8. debugregs are checked by Xen.
+ * 9. callback code selectors need checking.
*/
for ( i = 0; i < 256; i++ )
{
ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
}
-#if defined(__i386__)
- ctxt->fast_trap_idx = 0;
-#endif
-
/* No LDT. */
ctxt->ldt_ents = 0;
ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
}
-#if defined(__i386__)
- ctxt->fast_trap_idx = 0;
-#endif
-
/* No LDT. */
ctxt->ldt_ents = 0;
c->flags |= VGCF_VMX_GUEST;
#endif
-#ifdef ARCH_HAS_FAST_TRAP
- if ( (ed->arch.fast_trap_desc.a == 0) &&
- (ed->arch.fast_trap_desc.b == 0) )
- c->fast_trap_idx = 0;
-#endif
-
c->gdt_ents = 0;
if ( GET_GDT_ADDRESS(ed) == GDT_VIRT_START(ed) )
{
{
struct domain *d = ed->domain;
- SET_DEFAULT_FAST_TRAP(&ed->arch);
-
ed->arch.flags = TF_kernel_mode;
if ( d->domain_id != IDLE_DOMAIN_ID )
if ( test_bit(_VCPUF_initialised, &ed->vcpu_flags) )
return 0;
- if ( (rc = (int)set_fast_trap(ed, c->fast_trap_idx)) != 0 )
- return rc;
-
memset(ed->arch.guest_context.debugreg, 0,
sizeof(ed->arch.guest_context.debugreg));
for ( i = 0; i < 8; i++ )
stack_regs,
CTXT_SWITCH_STACK_BYTES);
unlazy_fpu(p);
- CLEAR_FAST_TRAP(&p->arch);
save_segments(p);
}
if ( !VMX_DOMAIN(n) )
{
- SET_FAST_TRAP(&n->arch);
+ set_int80_direct_trap(n);
switch_kernel_stack(n, cpu);
}
}
break;
}
- memcpy(dst+cur.vector, &cur, sizeof(cur));
+ memcpy(&dst[cur.vector], &cur, sizeof(cur));
+
+ if ( cur.vector == 0x80 )
+ init_int80_direct_trap(current);
+
traps++;
}
.long do_set_debugreg
.long do_get_debugreg
.long do_update_descriptor /* 10 */
- .long do_set_fast_trap
+ .long do_ni_hypercall
.long do_dom_mem_op
.long do_multicall
.long do_update_va_mapping
#include <asm/vmx.h>
#endif
-/* All CPUs have their own IDT to allow set_fast_trap(). */
+/* All CPUs have their own IDT to allow int80 direct trap. */
idt_entry_t *idt_tables[NR_CPUS] = { 0 };
void show_registers(struct cpu_user_regs *regs)
set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3);
}
-long set_fast_trap(struct exec_domain *p, int idx)
+void init_int80_direct_trap(struct exec_domain *ed)
{
- trap_info_t *ti;
-
- /* Index 0 is special: it disables fast traps. */
- if ( idx == 0 )
- {
- if ( p == current )
- CLEAR_FAST_TRAP(&p->arch);
- SET_DEFAULT_FAST_TRAP(&p->arch);
- return 0;
- }
-
- /* We only fast-trap vector 0x80 (used by Linux and the BSD variants). */
- if ( idx != 0x80 )
- return -1;
-
- ti = &p->arch.guest_context.trap_ctxt[idx];
+ trap_info_t *ti = &ed->arch.guest_context.trap_ctxt[0x80];
/*
* We can't virtualise interrupt gates, as there's no way to get
* the CPU to automatically clear the events_mask variable.
*/
if ( TI_GET_IF(ti) )
- return -1;
-
- if ( p == current )
- CLEAR_FAST_TRAP(&p->arch);
-
- p->arch.guest_context.fast_trap_idx = idx;
- p->arch.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
- p->arch.fast_trap_desc.b =
- (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13;
-
- if ( p == current )
- SET_FAST_TRAP(&p->arch);
-
- return 0;
-}
+ return;
+ ed->arch.int80_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
+ ed->arch.int80_desc.b =
+ (ti->address & 0xffff0000) | 0x8f00 | ((TI_GET_DPL(ti) & 3) << 13);
-long do_set_fast_trap(int idx)
-{
- return set_fast_trap(current, idx);
+ if ( ed == current )
+ set_int80_direct_trap(ed);
}
long do_set_callbacks(unsigned long event_selector,
struct arch_domain
{
l1_pgentry_t *mm_perdomain_pt;
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
l2_pgentry_t *mm_perdomain_l2;
l3_pgentry_t *mm_perdomain_l3;
#endif
int iobmp_limit; /* Number of ports represented in the bitmap. */
int iopl; /* Current IOPL for this VCPU. */
- /* Trap info. */
-#ifdef ARCH_HAS_FAST_TRAP
- struct desc_struct fast_trap_desc;
+#ifdef CONFIG_X86_32
+ struct desc_struct int80_desc;
#endif
/* Virtual Machine Extensions */
l2_pgentry_t *monitor_vtable; /* virtual address of monitor_table */
l1_pgentry_t *hl2_vtable; /* virtual address of hl2_table */
-#ifdef __x86_64__
+#ifdef CONFIG_X86_64
l3_pgentry_t *guest_vl3table;
l4_pgentry_t *guest_vl4table;
#endif
extern struct tss_struct init_tss[NR_CPUS];
-#ifdef ARCH_HAS_FAST_TRAP
+#ifdef CONFIG_X86_32
-#define SET_DEFAULT_FAST_TRAP(_p) \
- (_p)->guest_context.fast_trap_idx = 0x30; \
- (_p)->fast_trap_desc.a = 0; \
- (_p)->fast_trap_desc.b = 0;
-
-#define CLEAR_FAST_TRAP(_p) \
- (memset(idt_tables[smp_processor_id()] + \
- (_p)->guest_context.fast_trap_idx, \
- 0, 8))
-
-#define SET_FAST_TRAP(_p) \
- (memcpy(idt_tables[smp_processor_id()] + \
- (_p)->guest_context.fast_trap_idx, \
- &((_p)->fast_trap_desc), 8))
-
-long set_fast_trap(struct exec_domain *p, int idx);
+extern void init_int80_direct_trap(struct exec_domain *ed);
+#define set_int80_direct_trap(_ed) \
+ (memcpy(idt_tables[(_ed)->processor] + 0x80, \
+ &((_ed)->arch.int80_desc), 8))
#else
-#define SET_DEFAULT_FAST_TRAP(_p) ((void)0)
-#define CLEAR_FAST_TRAP(_p) ((void)0)
-#define SET_FAST_TRAP(_p) ((void)0)
-#define set_fast_trap(_p, _i) (0)
+#define init_int80_direct_trap(_ed) ((void)0)
+#define set_int80_direct_trap(_ed) ((void)0)
#endif
struct { char x[512]; } fpu_ctxt /* User-level FPU registers */
__attribute__((__aligned__(16))); /* (needs 16-byte alignment) */
trap_info_t trap_ctxt[256]; /* Virtual IDT */
- unsigned int fast_trap_idx; /* "Fast trap" vector offset */
unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
typedef struct {
} arch_vcpu_info_t;
-#define ARCH_HAS_FAST_TRAP
-
#endif
#endif
* This makes sure that old versions of dom0 tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define DOM0_INTERFACE_VERSION 0xAAAA1005
+#define DOM0_INTERFACE_VERSION 0xAAAA1006
/************************************************************************/
#define __HYPERVISOR_set_debugreg 8
#define __HYPERVISOR_get_debugreg 9
#define __HYPERVISOR_update_descriptor 10
-#define __HYPERVISOR_set_fast_trap 11 /* x86/32 only */
#define __HYPERVISOR_dom_mem_op 12
#define __HYPERVISOR_multicall 13
#define __HYPERVISOR_update_va_mapping 14